package com.kgc.project.projectservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kgc.project.entity.Projectinfo;
import com.kgc.project.projectservice.mapper.ProjectinfoMapper;
import com.kgc.project.service.ProjectinfoService;
import com.kgc.project.util.RedisUtil;
import org.apache.dubbo.config.annotation.Service;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.function.Function;

@Service
@Component
public class ProjectinfoServiceImpl implements ProjectinfoService {
    @Resource
    ProjectinfoMapper projectinfoMapper;
    @Resource
    RedisUtil redisUtil;
    @Resource
    RedissonClient redissonClient;


    @Override
    public PageInfo<Projectinfo> selectAll(Integer pageNum, Integer status) {
        PageHelper.startPage(pageNum,3);
        PageHelper.orderBy("id desc");
        List<Projectinfo> projectinfos;
        if (status!=0){
            projectinfos=projectinfoMapper.selectList(new QueryWrapper<Projectinfo>().eq("status",status));
        }else{
            projectinfos=projectinfoMapper.selectList(null);
        }
        PageInfo<Projectinfo> projectinfoPageInfo=new PageInfo<>(projectinfos);
        return projectinfoPageInfo;
    }

    @Override
    public Projectinfo selectById(Integer id) {
        Projectinfo projectinfo=null;
        Jedis jedis = redisUtil.getJedis();
        String key= "pro:"+id;
        String proJson = jedis.get(key);
        if (proJson!=null){
            //解决缓存穿透
            if (proJson.equals("empty")){
                return null;
            }
            //从redis中查询数据
            projectinfo= JSON.parseObject(proJson, Projectinfo.class);
            jedis.close();
        }else{
            //使用nx分布式锁，避免缓存击穿
            String skuLockKey="proId"+id;
            String skuLockValue= UUID.randomUUID().toString();
            String lockKey=jedis.set(skuLockKey,skuLockValue,"NX","PX",60*1000);
            if (lockKey.equals("OK")){
                //从数据库查数据
                projectinfo = projectinfoMapper.selectById(id);
                //解决缓存穿透,缓存雪崩
                if (projectinfo!=null){
                    //保存到redis
                    String jsonString = JSON.toJSONString(projectinfo);
                    //有效期随机，防止缓存雪崩
                    Random random=new Random();
                    int nextInt = random.nextInt(10);
                    jedis.setex(key,nextInt*60*1000,jsonString);
                }else {
                    jedis.setex(key,5*60*1000,"empty");
                }
                String script ="if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
                jedis.eval(script, Collections.singletonList(skuLockKey),Collections.singletonList(skuLockValue));
        }else{
                //如果分布式锁访问失败，线程休眠3秒，重新访问
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return projectinfo;
    }

    @Override
    public int updateProject(Projectinfo projectinfo) {
        int i = projectinfoMapper.updateById(projectinfo);
        return i;
    }

    @Override
    public boolean saveBatch(Collection<Projectinfo> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<Projectinfo> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean updateBatchById(Collection<Projectinfo> entityList, int batchSize) {
        return false;
    }

    @Override
    public boolean saveOrUpdate(Projectinfo entity) {
        return false;
    }

    @Override
    public Projectinfo getOne(Wrapper<Projectinfo> queryWrapper, boolean throwEx) {
        return null;
    }

    @Override
    public Map<String, Object> getMap(Wrapper<Projectinfo> queryWrapper) {
        return null;
    }

    @Override
    public <V> V getObj(Wrapper<Projectinfo> queryWrapper, Function<? super Object, V> mapper) {
        return null;
    }

    @Override
    public BaseMapper<Projectinfo> getBaseMapper() {
        return null;
    }
}
